package geno.app.aspecttest;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

import geno.app.MyRectangle;

privileged public aspect RectangleAspectFromJUnitTest {
		
	// tests for rectangle
	pointcut testingDefaultValue() : call(MyRectangle.new()) && within(geno.app.aspecttest.*);
	pointcut testingConstructorAssignment() : call(MyRectangle.new(int, int)) && within(geno.app.aspecttest.*);
	pointcut testingReturnValues() : call(int MyRectangle.getArea()) && within(geno.app.aspecttest.*);
	pointcut testingPrivateMethods() : call(boolean MyRectangle.checkInputs(String, String)) && within(geno.app.*); 
	
	// test if system out is called inside render
	pointcut systemout() : withincode(void *.draw()) && get(* System.out);
	pointcut testingProtectedMethods() : execution(void *.draw(..)); 
	
	//	pointcut testingExceptions() :
//	pointcut testingStaticFunction() :
	
	private int height = 0;
	private int width = 0;
		
	int around() : get(int *.height) && within(geno.app.*) {
		int value = proceed();
		System.out.println("Current height=" + value);
		return value;
	}
	
	int around() : get(int *.width) && within(geno.app.*) {
		int value = proceed();
		System.out.println("Current width=" + value);
		return value;
	}
	
	java.io.PrintStream around() : systemout() {
		java.io.PrintStream stream = proceed();
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		PrintStream newstream = new PrintStream(os);
		output = stream.toString();
		return stream;
	}
	
	String output = "This should change";
	
	before() : testingProtectedMethods() {
		System.out.println("Aspect Oriented Approach [Assertions] - Protected methods : ");
	}
	
	// traps call in render function
	after() : testingProtectedMethods() {
		System.out.println(output);
		System.out.println("SUCCESS.\n");
	}
		
	before() : testingPrivateMethods(){
		System.out.println("Aspect Oriented Approach [Assertions] - Private methods : ");
	}
	
	after() returning(boolean result): testingPrivateMethods() {
		if ( result ) {
			System.out.println("SUCCESS.\n");
		} else {
			System.out.println("FAILED.");			
		}
	}
	
	// Testing if computation is correct for getArea
	before() : testingReturnValues(){
		System.out.println("Aspect Oriented Approach [Assertions] - Returning values : ");
	}
	
	after() returning(int area): testingReturnValues() {
		if ( area == this.height * this.width ) {
			System.out.println("SUCCESS.\n");
		} else {
			System.out.println("FAILED.");			
		}
	}
	
	// Test if constructor assigns values correctly on each member variables
	before(int height, int width) : testingConstructorAssignment() && args(height, width) {
		System.out.println("Aspect Oriented Approach [Assertions] - Constructor Assignment : ");
		this.height = height;
		this.width = width;
	}
		
	after() returning(MyRectangle rect): testingConstructorAssignment() {
		if ( rect.getHeight() == this.height && rect.getWidth()== this.width ) {
			System.out.println("SUCCESS.\n");
		} else {
			System.out.println("FAILED.");
		}
	}
	
	// Test if default values are correct
	before() : testingDefaultValue() {
		System.out.println("Aspect Oriented Approach [Assertions] - Default values : ");
	}
	
	after() returning(MyRectangle rect): testingDefaultValue() {
		if ( rect.getHeight() == 0 && rect.getWidth()== 0 ) {
			System.out.println("SUCCESS.\n");
		} else {
			System.out.println("FAILED.");	
		}
	}
	
}
